home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / documents / Motif / perfNotes
Encoding:
Text File  |  1994-08-02  |  28.3 KB  |  728 lines

  1.  
  2.  
  3.  
  4.             MOTIF PERFORMANCE NOTES    
  5.  
  6.  
  7. There are a number of things that can be done to make Motif applications
  8. run as fast as possbile.  This document discusses a number of them.
  9. Organization of this document is:
  10.  
  11.     * Introduction
  12.     * General Observations
  13.     * General Motif-specific Application Issues
  14.     * Motif Start-up Issues
  15.     * Motif Run-time Issues
  16.     * Background processing
  17.  
  18.  
  19.  
  20. * INTRODUCTION
  21.  
  22. A Motif application must itself bear much of the responsibility for appearing
  23. snappy and responsive.
  24.  
  25. Of course the libraries (libXm, libXt, etc) need to work as well and as fast
  26. as they can.  But even if their time is reduced to zero, some (many?) apps
  27. will be less responsive than they could be.
  28.  
  29. This paper has a number of suggestions about how to improve the performance
  30. of Motif applications.  If you have suggestions, questions, clarifications,
  31. etc, about this paper, please send them to dave@sgi.com and they will be
  32. forwarded to the appropriate engineer.
  33.  
  34. Things this paper stresses include:
  35.  
  36.     * An app should respond to the GUI in foreground, and do any
  37.       time-consuming real work in background (i.e. workproc's, timer
  38.       routines, etc).
  39.       
  40.     * An app should take advantage of idle time to create interface
  41.       elements (e.g. popups) that are likely to be needed soon.  Any
  42.       GUI component should come up as instantly as possible.  Foreseeable
  43.       things should be created and ready to map when needed -- don't
  44.       wait until they are needed to create them.
  45.       
  46.     * If a component may be used again, don't destroy it -- just unmap it.
  47.     
  48. With a well-written application, there is (almost?) never any Motif/X11 reason
  49. for a popup or a dialog to be slow coming up -- even the first time.
  50.  
  51.  
  52.  
  53. * GENERAL OBSERVATIONS:
  54.  
  55.     * A high-performance Motif program is necessarily a producer-consumer
  56.       application.
  57.       
  58.       The GUI is the producer.  It produces actions to be taken on
  59.       behalf of the user.  Nothing must be allowed to interfere with
  60.       the producer rapidly becoming, and then remaining responsive.
  61.       
  62.       Even if the user cannot take a second action until the (possibly
  63.       slow) current action completes, the GUI should at least continue
  64.       to responsively support:
  65.         * modifying the long operation (if that makes sense)
  66.         * cancelling the long operation (if that makes sense)
  67.         * redrawing the interface as needed (e.g. expose events)
  68.  
  69.       The consumer is the part of the program that carries out the
  70.       actions.  Consumer code should be run in background, except
  71.       in those cases where the action is so fast that doing it in
  72.       foreground will not adversely impact the GUI's responsiveness.
  73.  
  74.       At start-up time, an application has absolutely nothing more
  75.       important to do than to get the initial GUI (action producer) up
  76.       and usable.  Anything else can be done afterwards.  Typically
  77.       an application should:
  78.  
  79.         * Get the initial minimal GUI up.  There must happen very
  80.           quickly.  How quickly this gets done has a major impact
  81.           on the user's perception of performance.
  82.         
  83.         * Queue up any other initialization that needs to be done.
  84.           The background/workproc/consumer will do these as fast as
  85.           it can.  This includes such things as:
  86.             * data initialization, such as a (possibly slow)
  87.               database access
  88.             * creation of any remaing user interface elements,
  89.               such as menus and popups.  The hope is that they
  90.               will be ready to be mapped when needed.
  91.         
  92.         * Put up a wait cursor if some of the queued initialization
  93.           needs to be completed before the user can interact with
  94.           the window.
  95.           
  96.         * Start processing events.  At least redraws will get handled,
  97.           even if the interface needs to wait for some
  98.           initialization to be fully functional.
  99.  
  100.         * Add to (or modify) the task queue for the consumer as
  101.           indicated by user input.
  102.           
  103.     * High performance GUI design Design must take the toolkit into
  104.       account.
  105.  
  106.       Motif does some things well, and some things less well.  Things
  107.       it does less well, and that are demonstrably important to SGI,
  108.       are good candidates for SGI new widgets and/or Motif extensions.
  109.  
  110.       In the meantime, a good GUI design must take toolkit realities
  111.       into account.  Layout and precise pixels may have to give a
  112.       little.  An attempt to precisely achieve something that does not
  113.       fit well with the toolkit is likely to cause two problems:
  114.         * A more difficult that necessary development effort.
  115.         * A worse than necesary performing product.
  116.  
  117.     * Compile -O2
  118.  
  119.     * use libmalloc
  120.  
  121.     * Do performance measurements!  (use cvspeed)  Odds are high that
  122.       performance of Motif and other heavily used software is less a
  123.       bottle-neck than your own new, untuned code.
  124.  
  125.       The application also may itself benefit from tuning.  This
  126.       suggestion is more than theoretical -- it comes from looking at
  127.       some real-world performance problems.
  128.       
  129.     * Note that just because Motif (or Xt) shows up high on a list
  130.       does not necessarily mean that Motif itself needs to be tuned.
  131.       It often means that your application is needlessly doing expensive
  132.       things.
  133.  
  134.       For example, if you repeatedly create and destroy hundreds of
  135.       widgets, or if you force unnecessary widget geometry management,
  136.       Motif or Xt functions will show up high on any performance chart.
  137.       The real question is "does the application really need to be
  138.       doing this?"
  139.  
  140.     * No one ever said that developing good-looking efficient modern
  141.       GUI's is simple -- the goal is a good interface for the end user,
  142.       but one cost may be a certain amount of developer complexity.
  143.  
  144.  
  145. * GENERAL MOTIF-SPECIFIC APPLICATION ISSUES
  146.  
  147.     * Toolkit applications, including Motif applications, are inherently
  148.       heavier than applications that use no toolkit, such as the zip
  149.       editor.  There is no getting around that.  This makes it even more
  150.       important to be careful how an application uses X and Motif.
  151.  
  152.     * Minimize the number of GL widgets in an application.  Each GL
  153.       widget has a separate GL context, and GL context switching is
  154.       expensive.  Having multiple GL widgets will visibly degrade your
  155.       performance.
  156.  
  157.     * Some are concerned that deep widget hierarchies, particularly
  158.       those with complex nested geometry management (form), is slow.
  159.       Others are not so sure -- you may have to experiment with this
  160.       one yourself.
  161.  
  162.     * When adding multiple items to a list, use XtSetValues on
  163.       the resources XmNitems and XmNitemCount rather than calling
  164.       XmListAddItem multiple times.
  165.  
  166.     * Use gadgets.  This is an area where reasonable folks have
  167.       different opinions.
  168.  
  169.         * Some folks say that you should use gadgets where possible
  170.           such as for menu items.
  171.       
  172.         * Other folks say that as X has handled windows better,
  173.           there is less of a win to using gadgets -- in fact in
  174.           some cases performance may degrade.
  175.  
  176.         * Note that, because "map" deals with windows (and gadgets
  177.           do not have windows), you cannot map or unmap a gadget.
  178.           As a practical matter, however, this shouldn't be a
  179.           significant limitation.  You generally will be mapping
  180.           and unmapping some sort of a shell (which may have gadgets
  181.           as descendants).
  182.  
  183.         * Using gadgets causes extra server traffic because the widget
  184.           parent must track all events for them -- even some they
  185.           wouldn't need to track themselves if they were widgets.
  186.  
  187.       We have seen cases where lots of widgets were involved, and when
  188.       gadgets were used instead there was a very noticeable speed-up.
  189.       For now, probably the best advice is:
  190.  
  191.         * If you have lots of things that could be gadgets,
  192.           it is probably worthwhile to make them gadgets.
  193.  
  194.         * It is generally easy to try both ways, so if in doubt
  195.           do try it and see.
  196.  
  197.  
  198. * APPLICATION START-UP ISSUES:
  199.  
  200.   There are some things an application can do to minimize user-perceived
  201.   start-up time:
  202.  
  203.     * To the extent possible, manage children all at once, rather than
  204.       one by one as they are created.  Doing them one by one, when they
  205.       could be done all at once, causes geometry calculation time to go
  206.       up non-linearly.
  207.  
  208.       Widgets can be managed efficiently by creating unmanaged widgets,
  209.       and then using XtManageChildren.  Do this instead of using
  210.       XtCreateManagedWidget, or doing XtManageChild after each widget
  211.       you create.
  212.  
  213.     * libXm updating the dropsite database is quite expensive.
  214.  
  215.       * Set drag and drop to dynamic.  Actually, this is encouraged on
  216.         functional grounds as well.  Furthermore, drag and drop
  217.         standardization through the X consortium is only supporting
  218.         the dynamic model.
  219.  
  220.       * Minimize time spent by the library updating its dropsite database.
  221.  
  222.         You may save considerable startup time by calling
  223.         XmDropSiteStartUpdate at the beginning of the widget creation
  224.         code and XmDropSiteEndUpdate when done.
  225.  
  226.         Likewise, use these calls to bracket any code that causes
  227.         substantial geometry management.  In one demo, doing this
  228.         gave a 70% improvement (from 10 seconds to 3 seconds for the
  229.         operation).
  230.  
  231.         Make sure you don't forget the XmDropSiteEndUpdate, otherwise
  232.         your drag and drop won't work correctly.
  233.  
  234.       * If your application still runs slowly, try turning off drag
  235.         and drop, except where you really do need it.
  236.  
  237.         This should only be done as a last resort, because it
  238.         interferes with consistency of the application.  The user
  239.         is left wondering where DND works and where it does not.
  240.         
  241.         However, some SGI applications have saved tens of seconds
  242.         of startup time by completely turning off DND.
  243.  
  244.     * Get the interface up ASAP.  Do things that can be delayed either
  245.       in a workproc or in other background processing after the
  246.       interface is up.  (Workproc's are described below).  Some
  247.       suggestions for typical things that ought to be done that way:
  248.  
  249.         * Compute intensive calculations not essential to getting
  250.           the initial interface up.
  251.  
  252.         * Time-intensive things, such as initializing access to
  253.           a database.
  254.  
  255.         * Creating any UI not initially needed (such as dialogs and
  256.           menus).
  257.  
  258.       Avoid just bringing up the UI and then locking out the user
  259.       for a long time either.  Although this is slightly better than
  260.       having nothing show up, it is not much better.
  261.  
  262.       With proper use of polling for events and/or workproc(s), an
  263.       application can generally get the time-consuming things done
  264.       and still be responsive to the user.
  265.  
  266.     * Take proper advantage of workproc's.  If there is a lot of
  267.       initialization to do, and that initialization is not critical to
  268.       getting the first interface up, the work should probably be done
  269.       in a workproc.  Doing so means that the main GUI can come up
  270.       promptly without waiting for the workproc work to complete.
  271.  
  272.       Create UI components that will be wanted later in workproc's.
  273.       If the component is already created when it is finally needed,
  274.       simply mapping it on demand is very fast.
  275.  
  276.       For example, creating any UI not initially needed (such as
  277.       dialogs and menus) can be done in a workproc --  create them,
  278.       realized and managed but unmapped, ready for mapping as needed.
  279.       In most cases, if the application is careful about which order
  280.       its workproc's are done, the gui item should be ready before the
  281.       user actually gets around to asking for it.
  282.  
  283.       The main code that brings up the dialog or menu needs to be
  284.       something like:
  285.  
  286.         if (already created)
  287.             map it (n.b. the code that created it will have
  288.                      already managed it)
  289.         else
  290.             set flag it is wanted
  291.  
  292.       And the workproc code needs a section after the item is created
  293.       (and managed, but not mapped) that goes something like:
  294.  
  295.         if (already needed)
  296.             map it
  297.  
  298.  
  299. * APPLICATION RUN-TIME ISSUES:
  300.  
  301.   Once up, Motif should not cause any serious slowdown for a well-written
  302.   application.  Some things to be careful of:
  303.  
  304.     * Use at most one GL widget in an application.  Having more than
  305.       one GL window in your application is very expensive because a
  306.       GL context switch is quite heavy-weight.
  307.  
  308.     * Take proper advantage of workproc's.
  309.     
  310.         * Example: the interactive performance of sliders in the
  311.           color chooser was terrible until the slider processing
  312.           was moved to a workproc.  Then the performance became
  313.           just fine.
  314.  
  315.         * Example: if a little-used UI component is called, it
  316.           may pay to at that time use a workproc to create and
  317.           manage (but not map) related ones that the user is likely
  318.           to need.  Then they can be quickly mapped when requested.
  319.  
  320.         * Note: do not remain in a workproc more than a fraction
  321.           of a second without ensuring that events get processed.
  322.           This point is discussed in more detail below.
  323.  
  324.     * Reuse components, such as dialogs, wherever you can.  Do not
  325.       create them as needed and then immediately destroy them when
  326.       done.  Instead, save their ID and unmap them.  They can be
  327.       quickly re-mapped later when needed.
  328.  
  329.       Note that this suggestions is consistent with creating
  330.       most UI components (other than the initial UI) in workproc's.
  331.  
  332.     * Wherever possible use the first of these that you can:
  333.  
  334.         (1) Use map/unmap to make ui components come and go.
  335.             This has always been good programming practice.
  336.           
  337.             As of the current level of Motif, with its need to keep
  338.             drag and drop information up to date, failing to do this
  339.             has become much more expensive than it used to be.
  340.  
  341.             N.b. -- of course the component must be managed when it
  342.             is first created.
  343.  
  344.         (2) Use manage/unmanage to make ui components come and go,
  345.             only if you really cannot just map/unmap them.  (Of
  346.             course the component must be managed once when it is
  347.             first created.)
  348.  
  349.             This is significantly inferior to map/unmap, but if the
  350.             geometry really is changing may be necessary.
  351.  
  352.             If you are affecting much geometry calculation, bracket
  353.             your operation with XmDropSiteStartUpdate and
  354.                 XmDropSiteEndUpdate.
  355.  
  356.         (3) Use create/destroy as a last resort.  This is quite
  357.             expensive.  It should only be done once -- preferably
  358.             at a time the user isn't waiting for it.
  359.           
  360.             If the user does something that needs a new UI component
  361.             up, you should normally be able to just map one that
  362.             was either used before, or was created anticipating
  363.             this need.  If the user is doing something unusual,
  364.             you may need to create a new one -- but that should not
  365.             be the common case.
  366.  
  367.             Any time you do create a component, save it if it might
  368.             get used again later.  It will be much cheaper to remap
  369.             it, possibly setting some hew resources first, than to
  370.             destroy it now and create it again later.
  371.  
  372.  
  373. * BACKGROUND PROCESSING
  374.  
  375.   An application's interface should always remain as responsive to a user
  376.   as possible.  This requires that:
  377.  
  378.     * Startup and foreground processing need to be very quick
  379.     * Anything lengthy should be done in background
  380.     * Any background processing must not lock out the foreground for
  381.       more than a small fraction of a second
  382.     * Even if the background processing must continue for a long time
  383.       uninterrupted, it should at least arrange to process expose events.
  384.  
  385.   There are several possible ways to do background processing:
  386.     * Use one or more workproc's to do processing whenever there are no
  387.       pending X events.  Just don't stay in the workproc more than a
  388.       fraction of a second without processing events (see below).
  389.  
  390.     * Use XtAppAddTimeout() to call function(s) on a regular basis.
  391.       You might want to do this instead of using a workproc if your
  392.       background processing is more at regular intervals than continuous.
  393.  
  394.     * Process from the application's main-line code.  In this case, the
  395.       application must do its own regular event polling and dispatching.
  396.  
  397.   Xt is *event* driven, not *interrupt* driven.  No background processing,
  398.   whether it be a workproc, a timeout routine, or just ordinary code,
  399.   will be interrupted by X.  If the background processing really must run
  400.   a long time, then it should voluntarily relinquish control from time to
  401.   time to ensure that events get serviced frequently.  If it does not do so,
  402.   processing user input will be delayed.
  403.  
  404.   If you are using either workproc(s) or timeout routine(s), and if no one
  405.   of them is longer than a small fraction of a second long, then event
  406.   handling will be responsive without taking any special action.
  407.  
  408.   Keeping a application responsive, even if needs time-consuming
  409.   background processing, need not be too restrictive.  It just means that
  410.   the background processing must be properly structured.  One way to think
  411.   of this is that is is the reverse of the usual -- instead of relying on
  412.   Xt to call the application from time to time for a little processing,
  413.   the application calls Xt from time to time to let Xt do a little
  414.   processing.  There are several ways this can be done:
  415.  
  416.     * You can use a workproc that at frequent intervals notes its own
  417.       state and returns FALSE.  That will let any pending events be
  418.       serviced, and then the workproc will be called again.  When the
  419.       workproc is finally done, it needs to return TRUE so it will not
  420.       get called again.
  421.  
  422.       Note that workproc's are called in order.  If you want several
  423.       workproc's to get time in any other manner, you must arrange that
  424.       yourself.
  425.  
  426.     * You can use a timeout routine that at frequent intervals notes
  427.       its own state, sets another timeout, and returns.  That will let
  428.       any pending events be serviced, and then when the timer goes off
  429.       the routine will be called again.
  430.  
  431.       Note that timeout's are higher priority than workproc's.
  432.       No workproc will get run unless there are no pending events
  433.       and also no expired timeouts.  Thus, if your timeout routine
  434.       set another timeout, and if it times out before the routine exits,
  435.       events will get processed but no workproc will ever get called.
  436.  
  437.       Doing this is one way to get events serviced during a long timeout
  438.       routine.  It in effect turns your timeout routine into the
  439.       highest priority workproc.  If you want a real workproc called
  440.       before such a timeout routine is done, the timeout routine must
  441.       do that itself.
  442.  
  443.     * In some cases, it will be difficult (or impossible) to
  444.       keep track of state, exit, and be restarted.  An example
  445.       of this might be a lengthy recursive algorithm.
  446.  
  447.       In that case, the background processing needs to do its own
  448.       regular polling and event dispatching.  When to do the polling
  449.       can be determined in any of a number of ways, such as:
  450.         * algorithmically (perhaps each time through the process's
  451.           main loop
  452.         * after each significant section of the background task
  453.         * poll from a timeout routine.
  454.  
  455.       If a workproc must be called, it is up to the background processing
  456.       to do so itself.
  457.   
  458. * OVERVIEW OF WORKPROC'S:
  459.  
  460.     * Xt provides a limited form of background processing, the
  461.       XtWorkProc.  An XtWorkProc is called when there are no events
  462.       pending.  An application may have more than one workproc.
  463.  
  464.     * Register each workproc, using XtAppAddWorkProc().  The easiest
  465.       way to preserve interactive response may be to register more than
  466.       one workproc.
  467.  
  468.     * If a workproc is to be run at any time other than the standard
  469.       (in order, and only when no events are pending), the application
  470.       must call the workproc(s) directly.
  471.       
  472.     * There is no non-blocking way to tell that a workproc has been
  473.       registered.  If this knowledge matters to an application, the app
  474.       must keep track of it itself.
  475.  
  476.     * Workproc's are unrelated to X events, and are of lower priority.
  477.       The only connection is that a workproc is called from the X event
  478.       loop when there are no X events to service.  Once a workproc is
  479.       called, nothing else will run until the workproc returns.
  480.  
  481.     * When a workproc returns:
  482.         * any pending events will be serviced
  483.         * if the workproc returned FALSE, it will be run again
  484.         * if the workproc returned TRUE, it will be un-registered,
  485.           and the next workproc (if any) will be run.
  486.  
  487.     * No workproc runs until all higher priority workproc's have
  488.       completed.  If your application needs anything else, it will
  489.       have to do its own scheduling (instead of depending on Xt).  In
  490.       such a case, it will not register most or all of its workproc's.
  491.       It will just arrange to call them itself.
  492.  
  493.     * For more than one workproc, there is a defined order in which
  494.       they will be called.  One will not be run until all higher
  495.       priority workproc's have been run to completion (i.e. returned
  496.       TRUE).
  497.         * For workproc's registered when not already running a
  498.           workproc, the last registered is the highest priority.
  499.  
  500.         * workproc's registered from within a workproc are lower
  501.           priority than that workproc.
  502.  
  503.     * You might use more than one workproc if:
  504.         * Putting clearly separate tasks in distinct workproc's
  505.           is the cleanest way to write the application.
  506.  
  507.           For example, if your initialization needs to create
  508.           several dialog windows, you could register several
  509.           workproc's to do so.  Note that this could be the same
  510.           workproc each time, perhaps with different client data.
  511.  
  512.           The workproc would keep track of which action to perform
  513.           each time either by the different client data argument,
  514.           or by keeping its own internal static records.
  515.  
  516.         * One long workproc task can be broken up into a number
  517.           of acceptably short tasks.  By putting them in separate
  518.           workproc's, you save the trouble of ensuring that the
  519.           workproc periodically returns to the X event loop.
  520.           
  521.           If you keep all in one workproc, you are responsible
  522.           for preserving interactivity -- by using polling or
  523.           timeouts or whatever else to ensure that the one workproc
  524.           doesn't hog the cpu for too long.
  525.  
  526. * POLLING FOR EVENTS
  527.  
  528.   Long-running background tasks should poll for, and process, events.
  529.   At a minimum, the process should honor expose events.  If expose events
  530.   are all that is being processed, the application should put up a busy
  531.   cursor.
  532.  
  533.   Following is a code sample that will poll for and process all events.
  534.   Note that if you are in a callback and there is a pending event that would
  535.   trigger the callback, you will get re-entered.  If you are in a timeout
  536.   routine and another timer for that routine has gone off, you will also
  537.   get re-entered.  Your application is responsible for handling such a
  538.   case.  Of course, you can avoid the problem by keeping your callbacks and
  539.   timeout routines short enough that polling is not necessary.
  540.  
  541.         while (XtAppPending(appContext))
  542.             XtAppProcessEvent(appContext, XtIMAll);
  543.  
  544.   The manual pages describe these functions and their parameters in more
  545.   detail.  You can do such things as process only specific events.  This
  546.   document is only an overview.  For details, read the appropriate
  547.   sections from the following references:
  548.  
  549.     * "X WINDOW SYSTEM TOOLKIT", by Asente & Swick
  550.          PART I PROGRAMMER'S GUIDE
  551.         section 6.8 "Getting Events"
  552.             6.9 "Dispatching Events"
  553.             6.10 "Custom Event-Dispatching Loops"
  554.             6.11 "Background Work Procedures"
  555.             6.11 "Using Xlib Event Routines"
  556.          PART II SPECIFICATION
  557.         section 7.4 "Querying Event Sources"
  558.             7.5 "Dispatching Events"
  559.             7.6 "The Application Input Loop"
  560.             7.8 "Adding Background Work Procedures"
  561.  
  562.     * "X Toolkit Intrinsics Programming Manual, OSF/Motif 1.2
  563.        Edition", (O'Reilly Vol 4)
  564.         section 9.6 "Work Procedures"
  565.  
  566.     * "X Toolkit Intrinsics Reference Manual", (O'Reilly Vol 5)
  567.             XtWorkProc
  568.             XtAppAddWorkProc()
  569.             XtRemoveWorkProc()
  570.             XtAppPending()
  571.             XtAppNextEvent()
  572.             XtAppProcessEvent()
  573.  
  574.     * "Motif Programming Manual" (O'Reilly Vol 6)
  575.         section 20.2   "Working Dialogs"
  576.             20.2.1 "Using Work Procedures"
  577.             20.2.2 "Using Timers"
  578.             20.2.3 "Processing Events Yourself"
  579.  
  580.     * "The X Window System, Programming and Applications with Xt,
  581.       OSF/Motif Edition", by Doug Young
  582.         section 5.7 "USING WORKPROCS"
  583.  
  584.  
  585.  
  586. * NON_TOOLKIT X PERFORMANCE NOTES
  587.  
  588.   *  Don't needlessly complicate window clipping.  For example:
  589.  
  590.      +----------+
  591.      |          |
  592.      |  A   +-----------+
  593.      |      |           |
  594.      +------|    B      |
  595.         |           |
  596.         +-----------+
  597.  
  598.        Drawing performance to window A is reduced because it doesn't
  599.        have a single rectangular clip.  For toplevel windows, the way
  600.        windows are overlapped is up to the user via the window manager
  601.        but inside your application hierarchy, it should avoided.
  602.  
  603.   * If you use a GC to draw to both a pixmap and a window, you pay the
  604.     price of a full GC validation every time you switch between the pixmap
  605.     and the window on SGI machines (the code to draw to the graphics
  606.     hardware is totally different from the dumb frame buffer hardware
  607.     used for pixmaps and so the hooks in the GC must be totally revalidated
  608.     each time you switch between a window and a GC).  
  609.  
  610.     This should not be a key performance issue but if you have code like:
  611.  
  612.        create window A
  613.        create pixmap B
  614.        create GC C
  615.        repeat a lot of times
  616.           do some primitive to A using C
  617.           do some primitive to B using C
  618.  
  619.     The code will be faster if you use:
  620.  
  621.        create window A
  622.        create window B
  623.        create GC C
  624.        create GC D (the same as C)
  625.        repeat a lot of times
  626.           do some primitive to A using C
  627.           do some primitive to B using D
  628.  
  629.   * The SGI X server does allow you to run with a default depth other than
  630.     8 (the default) using the -depth option (see Xsgi man page).  Most X
  631.     clients use the default visual.  This means that all of their pixmaps
  632.     will of the default depth.  A pixmap of depth 12 takes twice the memory
  633.     of a pixmap of depth 8.  A pixmap of depth 24 takes four times the memory
  634.     of a pixmap of depth 8.  Also the rendering code to these pixmaps is
  635.     slower.
  636.  
  637.     If you need an X client to use a 24-bit TrueColor visual, the best
  638.     thing is to write that program to find such a visual instead of
  639.     reconfiguring the X server to use a 24-bit TrueColor visual.
  640.  
  641.   * Compress expose events.  Naive redraws will not only be visually
  642.     unattractive but also waste the X servers time.  Motif and Xt do this
  643.     for you.
  644.  
  645.  
  646. BACKING STORE and SAVE UNDER
  647.  
  648. Backing store and save under are intended as performance optimizations.
  649. In practice, using them may instead lead to performance degradation.
  650.  
  651. Backing store and save under for non-GL windows:
  652.  
  653.     * Backing store and save under will never work for IrisGL
  654.       clients.  That is, IrisGL pixels will not be saved and
  655.       restored.
  656.  
  657.     * Backing store and save under will never work for OpenGL that is
  658.       rendered directly (rather than through the X server).
  659.  
  660.     * Backing store and save under may possibly work in a future
  661.       release, for OpenGL that is rendered through the X server.
  662.       However, that is definitely not currently committed and may never
  663.       happen.
  664.  
  665.     * The difference in these three cases is the ability to render
  666.       to pixmaps, based on the window's clip.
  667.         * IrisGL will never render to pixmaps
  668.           
  669.         * Direct-rendered OpenGL clients have neither knowledge of
  670.           the window's clip, nor the tolerance for any additional
  671.           level of indirection that would affect rendering performance.
  672.  
  673.         * Indirectly rendered OpenGL clients will share the server's
  674.           knowledge of the clip and can tolerate the extra level of
  675.           indirection needed to decide whether to render to pixmap
  676.           or to the screen
  677.  
  678.  
  679. Backing store and save under for non-GL windows:
  680.  
  681.     * Most Xt apps may be better off without using either backing store
  682.       or save unders.
  683.  
  684.     * Consider a control panel with a few buttons and a few strings.
  685.       Backing store is almost certainly a major lose in 99+% of
  686.       configurations, because rendering a few rectangles and a little
  687.       text should be much faster than saving and restoring the affected
  688.       pixels.
  689.  
  690.     * On the other hand, if you have a very expensive, difficult
  691.       rendering to do, and you're essentially blitting pixels anyway,
  692.       then backing store can
  693.  
  694.         * prevent you from having to recalculate (if your app is
  695.           dumb enough to have to recalculate)
  696.  
  697.         * prevent the pixels from having to go over the net.
  698.  
  699.     * The app developer must understand the backing store implementation
  700.       and think the performance issues through.
  701.  
  702.  
  703. One place that backing store contributes to poor perceived performance
  704. is using window managers with opaque move enabled (mwm and 4Dwm support
  705. opaque move).  When you move an opaque window over a backing store window,
  706. you are asking the server to do lots of backing store operations.  The
  707. result can be very sluggish opaque moves.
  708.  
  709. If clients handle their own redraws, the movement can be much more fluid
  710. because clients catch up on exposes and can compress them.  The visual
  711. effect is not nearly as jerky.
  712.  
  713. TODO:
  714.     * Test gadget creation speed.  Perhaps this would make a good
  715.       demo.
  716.  
  717.  
  718. * SGI has some constraints in what we can do with/to the Motif library:
  719.  
  720.     * Motif itself is constrained by Xt and X11.
  721.  
  722.     * Motif is a standard, so we can only do things that will
  723.       not change any application-visible behavior.
  724.  
  725.     * We need to merge new releases of Motif several times per year.
  726.       We cannot make changes that are on a scale that will prevent
  727.       us keeping up with the standard.
  728.